﻿namespace AddressBook.Business.MailingList
{
	#region "Using Statements"

	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Text;

	using Csla;
	using Csla.Data;
	using Csla.Validation;

	#endregion

	[Serializable]
	public class MailingList : BusinessBase<MailingList>
	{
		#region "Business Methods"

		#region "Private Static Member Variables"

		private static PropertyInfo<Int32> IdProperty = RegisterProperty<Int32>(e => e.Id);
		private static PropertyInfo<String> NameProperty = RegisterProperty<String>(e => e.Name);
		private static PropertyInfo<SmartDate> ModifiedDateProperty = RegisterProperty<SmartDate>(e => e.ModifiedDate);
		private static PropertyInfo<MailingListEntries> GuestsProperty = RegisterProperty<MailingListEntries>(e => e.Guests);

		#endregion

		#region "Public Properties"

		public Int32 Id
		{
			get { return GetProperty(IdProperty); }

			internal set { LoadProperty(IdProperty, value); }
		}

		public String Name
		{
			get { return GetProperty(NameProperty); }

			set { SetProperty(NameProperty, value); }
		}

		public String ModifiedDate
		{
			get { return GetProperty(ModifiedDateProperty).ToString(); }
		}

		public MailingListEntries Guests
		{
			get
			{
				if (!(FieldManager.FieldExists(GuestsProperty)))
				{
					LoadProperty(GuestsProperty, MailingListEntries.NewMailingListEntries());
				}

				return GetProperty(GuestsProperty);
			}
		}

		#endregion

		#endregion

		#region "Factory Methods"

		public static MailingList NewMailingList()
    {
      return DataPortal.Create<MailingList>();
    }

		public static MailingList GetMailingList(Int32 id)
    {
      return DataPortal.Fetch<MailingList>(new SingleCriteria<MailingList, Int32>(id));
    }

		public static void DeleteMailingList(Int32 id)
    {
      DataPortal.Delete(new SingleCriteria<MailingList, Int32>(id));
    }

		private MailingList()
    { /* require use of factory methods */ }

		#endregion

		#region "Data Access"

		[RunLocal()]
		protected override void DataPortal_Create()
		{
			using (BypassPropertyChecks)
			{
				ValidationRules.CheckRules();
			}
		}

		private void DataPortal_Fetch(SingleCriteria<MailingList, Int32> criteria)
		{
			using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
			{
				// get event data
				AddressBook.Business.Model.List listData = ctx.DataContext.Lists.First(l => l.Id == criteria.Value);

				using (BypassPropertyChecks)
				{
					this.Id = listData.Id;
					this.Name = listData.Name;

					LoadProperty(ModifiedDateProperty, listData.ModifiedDate);

					//Load Child object
					LoadProperty(GuestsProperty, MailingListEntries.GetMailingListEntries(listData.Entries.ToArray()));
				}
			}
		}

		[Transactional(TransactionalTypes.TransactionScope)]
		protected override void DataPortal_Insert()
		{
			using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
			{
				// insert event data
				using (BypassPropertyChecks)
				{
					AddressBook.Business.Model.List listData = new AddressBook.Business.Model.List();

					listData.Name = this.Name;
					listData.ModifiedDate = System.DateTime.Now;

					ctx.DataContext.Lists.InsertOnSubmit(listData);
					ctx.DataContext.SubmitChanges();

					this.Id = listData.Id;
				}

				FieldManager.UpdateChildren(this);
			}
		}

		[Transactional(TransactionalTypes.TransactionScope)]
		protected override void DataPortal_Update()
		{
			using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
			{
				AddressBook.Business.Model.List listData = ctx.DataContext.Lists.First(l => l.Id == this.Id);

				// update event data
				using (BypassPropertyChecks)
				{
					listData.Name = this.Name;
					listData.ModifiedDate = System.DateTime.Now;

					ctx.DataContext.SubmitChanges();
				}

				FieldManager.UpdateChildren(this);
			}
		}

		[Transactional(TransactionalTypes.TransactionScope)]
		protected override void DataPortal_DeleteSelf()
		{
			DataPortal_Delete(new SingleCriteria<MailingList, Int32>(this.Id));
		}

		[Transactional(TransactionalTypes.TransactionScope)]
		private void DataPortal_Delete(SingleCriteria<MailingList, Int32> criteria)
		{
			using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
			{
				// get event data
				AddressBook.Business.Model.List listData = ctx.DataContext.Lists.First(l => l.Id == criteria.Value);

				// delete the guests assigned to this event.
				foreach (AddressBook.Business.Model.Entry entry in ctx.DataContext.Entries.Where(e => e.ListId == listData.Id))
				{
					ctx.DataContext.Entries.DeleteOnSubmit(entry);
				}

				ctx.DataContext.SubmitChanges();

				// delete event data
				ctx.DataContext.Lists.DeleteOnSubmit(listData);
				ctx.DataContext.SubmitChanges();

				LoadProperty(GuestsProperty, MailingListEntries.NewMailingListEntries());
			}
		}

		#endregion
	}
}
